package Pruebas;
/**
 *
 * @author Herminio y Wilfredo
 * Puedes ver los cambios???
 * mas caambios........
 * unos cuantos mas............
 * jajajjajaj  ya puedo verlo
 */ 
public class Simplex {
   
    int MAXI=100;
    double P[][];
    int dimX;
    int dimY;
    double RS[][]= new double[MAXI][MAXI];//Matriz de resultados
    int NT;//Nº de filas de la matriz de resultados.
    String []RS0 = new String[MAXI];//primera columna de la matriz resultados
    
    String Resul;
    
    public Simplex(int dimX,int dimY){
        this.dimX = dimX;
        this.dimY = dimY;
        P = new double[dimX][dimY];
    }
    
    public Simplex(){
        
    }
    
    public static void main(String []args){
        double M[][] = new double[3][5];
        
        double P[][] = new double[2][4];
        double v[] = new double[3];
        
        
        M[0][0] = -4;   M[0][1] = -1;   M[0][2] = 0;    M[0][3] = 0;    M[0][4] = 0;
        //------------------------
        M[1][0] = 8;    M[1][1] = 2;    M[1][2] = 1;    M[1][3] = 0;    M[1][4] = 16;
        M[2][0] = 5;    M[2][1] = 2;    M[2][2] = 0;    M[2][3] = 1;    M[2][4] = 12;
               
        //----------------------------------------Z
        v[0] = -4;   v[1] = -1;  v[2] = 0;
        //------------------------
        P[0][0] = 8;    P[0][1] = 2;   P[0][2] = 16; P[0][3]= 45;
        P[1][0] = 5;    P[1][1] = 2;   P[1][2] = 12; P[1][3]= 25;
        
        //---------------------------------------z
       
        Simplex obj = new Simplex();
                
        System.out.println("Matriz Original"); 
        
        obj.imprimir(obj.ObtenerTotal(P,2,4,v), 3, 6);
        
        //obj.metodoMaxSimplex(M,3,5);
        
    }
    
     public boolean CalcularSimplex(double[][] MTotal, int nF, int nC, String Tipo) {
        //P = new double[nF][nC];
        boolean band;
        P = MTotal;
         
        if("Max".equals(Tipo)){
            band = metodoMaxSimplex(P,nF,nC);
        }else{
            band = metodoMinSimplex(P,nF,nC);
        }
        return band;
    }
    //Metodo que nos ayuda a calcular la funcion maxima de objetivo
    public boolean metodoMaxSimplex(double [][]A,int nf,int nc){
       boolean band = true;
       dimX = nf;
       dimY = nc;
       String [] B = new String[nf];  
       Elemento min,piv;
       double bb;
       int i=0;
       //enviamos a calcular el valor min
       min = calcMin(A,nc);
       bb = min.val; 
       llenarColumna0(B,nf);
       
       
      
       guardarM(A,i);
       guardarColumna0(B,i); 
       //esta iteracion se realiza mientra no exita mayor valor  de signo negativo
       while(bb < 0&&band ){
           
            System.out.println("Columna Min: " + min.getVal()+ "(i,j) = "+ min.getFil()+" , "+ min.getCol());
            
            piv = calcPivote(min,A,nf,nc);
            
            if(piv.getVal()!=0){    
                //entra el valor del pivote y sale el valor de la columna
                B[piv.getFil()] = "X"+(piv.getCol()+1);


                System.out.println("Elemento Pivote: " + piv.getVal()+ " (i,j) = "+ piv.getFil()+" , "+ piv.getCol());
                hacerCero(piv,nf,nc,A);

                System.out.println("Metodo Simplex");


                //Verificamos si nuestra fila de coeficientes posee algun valor negativo, caso contrario el ejercico finaliza
                min = calcMin(A,nc);
                bb = min.getVal();
                i++;
                guardarM(A,i);//Guarda los valores de la matriz....en la matriz Resultado.
                guardarColumna0(B,i);//Guarda los valores de la Columna en la matriz [i][0]
            }
            else{
                band = false;
            }
            
       }
       
      Resul = mostrarResultado(A, B, nf);
       imprimir(RS,NT,nc);
       return band;
    }
 
        //Metodo que nos ayuda a calcular la funcion maxima de objetivo
    public boolean metodoMinSimplex(double [][]A,int nf,int nc){
       
       boolean band = true;
       dimX = nf;
       dimY = nc;
       String [] B = new String[nf];  
       Elemento max,piv;
       double bb;
       int i=0;
       //enviamos a calcular el valor max
       max = calcMax(A,nc);
       bb = max.val; 
       llenarColumna0(B,nf);
       
       guardarM(A,i);
       guardarColumna0(B,i); 
       //esta iteracion se realiza mientra no exita mayor valor  de signo negativo
       while(bb > 0 && band){
           
            System.out.println("Columna Max: " + max.getVal()+ "(i,j) = "+ max.getFil()+" , "+ max.getCol());
            
            piv = calcPivote(max,A,nf,nc);
            
            if(piv.getVal()!=0){
                    //entra el valor del pivote y sale el valor de la columna
                    B[piv.getFil()] = "X"+(piv.getCol()+1);

                    System.out.println("Elemento Pivote: " + piv.getVal()+ " (i,j) = "+ piv.getFil()+" , "+ piv.getCol());
                    hacerCero(piv,nf,nc,A);

                    System.out.println("Metodo Simplex");

                    //Verificamos si nuestra fila de coeficientes posee algun valor negativo, caso contrario el ejercico finaliza
                    max = calcMax(A,nc);
                    bb = max.val;
                    i++;
                    guardarM(A,i);//Guarda los valores de la matriz....en la matriz Resultado.
                    guardarColumna0(B,i);//Guarda los valores de la Columna en la matriz [i][0]
            }
            else{
               band = false; 
            }
       }
       
       mostrarResultado(A, B,nf);
       imprimir(RS,NT,nc);
       return band;
    }
    
    public String RResultado(){
        return Resul;
    }
    
   public String mostrarResultado(double[][] XX, String RR[], int Xf){
       String DF = "";
       boolean bind;
       
       for(int i=0;i<Xf;i++){
           bind = false;
           for(int j =1;j<Xf;j++){
               if(("X"+(i+1)).equals(RR[j])){
                   DF = DF + RR[j]+" = " +XX[j][dimY-1]+";\n";
                   j = Xf;
                   bind=true;
               } 
           }
           if(!bind){
                   DF = DF + "X"+(i+1)+" = 0;\n";
           }
       }       
       return DF + "Total = "+XX[0][dimY-1];
   }
    
    //funcion que calcula el menor valor
    public Elemento calcMin(double [][]X,int dimC) {
        Elemento mm;
        double vv = X[0][0];
        int t=0;
        for(int i =1;i<dimC;i++){
            if( X[0][i] < vv){
                vv = X[0][i];
                t=i;
            }
        }
        mm=new Elemento(0, t, vv);
        return mm;
    }
    
    public Elemento calcMax(double [][]X,int dimC) {
        Elemento mm;
        double vv = X[0][0];
        int t=0;
        for(int i =1;i<dimC;i++){
            if( X[0][i] > vv){
                vv = X[0][i];
                t=i;
            }
        }
        mm=new Elemento(0, t, vv);
        return mm;
    }
    
    
    private Elemento calcPivote(Elemento Xmin, double[][] X,  int dimF,int dimC) {
        Elemento mm;
        double num,den;
        double vv = 1000000000.0;
        int t=0;
        //empezamos a contar desde la segunda fila
        for(int i=1;i<dimF;i++){
            num = X[i][dimC-1];
            den = X[i][Xmin.getCol()];
            //condicional que nos ayuda a elegir el menor optimo, distinto de 0
            if(den>0&&num>0){
                //elige el menor de todos...XD
                if(vv>num/den){
                    vv = num/den;
                    t=i;
                }    
            } 
        }
        if(t!=0){
            mm = new Elemento(t,Xmin.getCol(),X[t][Xmin.getCol()]);
            
        }else{       
            mm =  new Elemento(t,Xmin.getCol(),0);
        }
        return mm;
    }

    private void hacerCero(Elemento xpiv, int dimF, int dimC, double[][] X) {
       double masc; 
       for(int j=0;j<dimC;j++){
            X[xpiv.getFil()][j]= X[xpiv.getFil()][j]/xpiv.getVal();
       }
    
       //hacemos cero las demas filas...xD
       for(int i=0;i<dimF;i++){
           masc = X[i][xpiv.getCol()];//el numero que debemos multiplicara para hacer cero
           //verificamos que la fila no sea igual a la del elemento pivote.
           if(i!=xpiv.getFil()){
                for(int j=0;j<dimC;j++){
                   X[i][j]= X[i][j] - masc*X[xpiv.getFil()][j];
                }
           }
       }
        System.out.println("Imprimendo Hacer Cero");
        imprimir(X,dimF,dimC);
    
    }
    
    public void imprimir(double X[][],int dimF,int dimC){
        for(int i = 0;i<dimF;i++){
            for(int j = 0;j<dimC;j++){
                System.out.print("\t" + X[i][j]);
            }
            System.out.println("");
        }
    }

 
//Los valores pasados por esta funcion son:
//DimF: Nº de fila de la matriz Mat
//DimC: Nº de columnas de la matriz Mat              2          4
   public double[][] ObtenerTotal(double[][] Mat, int DimF, int DimC, double[] DO) {
       int nf = DimF+1;//Nº de filas de la Matriz Total
       int nc = DimF+DimC; //Nº de columnas de la matriz Total
       double MT[][] = new double[nf][nc];//Matriz total
       double MI[][] = new double[nf+1][DimF+1];//Matriz Identidad
       
       //Colocamos los valores de la funcion objetivo a la fila 0 de la matriz aumentada......!
       for(int k = 0; k<nc; k++){
           // k < 3         
           if(k<DimC-1){
                MT[0][k]=(-1)*DO[k];
           }else {
                MT[0][k]= 0;
           }
       }
       
       /* -- */
       for(int t =0; t<DimF;t++){
           MI[0][t] = 0;
       }
       
       
        for(int i = 1; i<nf; i++){
            for(int j = 0; j<DimF; j++){
                if((i-1)==j){   
                    MI[i][j]= 1;
                }
                else{
                    MI[i][j]= 0;
                }                
            }
        }
        //La matrizaumentada es MI 
        //Ahora concatenamos las dos matrices ....Mat y MI
         
        for(int i = 1; i<nf; i++){
            for(int j = 0; j<nc; j++){
                //      4-1
                if(j<DimC-1){
                    MT[i][j] = Mat[i-1][j]; 
                }
                
                //          6-1  
                else if(j!= nc-1){
                    MT[i][j] = MI[i][j-(DimC-1)]; 
                }
                
                //           4-1  
                else {
                    MT[i][j] = Mat[i-1][DimC-1]; 
                }
               
            }
        }
   
        return MT;
   }

   public void guardarM(double X[][],int c){
        int i1 = dimX*c;
        
        for(int i =0;i<dimX;i++){
            for(int j=0;j<dimY; j++){
                RS[i1][j] = X[i][j]; 
            }
            i1++;
        }
         NT= i1;   
    }
    
   public void llenarColumna0(String[] B, int nf) {
         B[0]= "Cj";
         for(int i=1;i< nf;i++){
            B[i]= "X"+(i+nf-1);
        }
    }

   public void guardarColumna0(String[] B, int c) {
        int i2 = dimX*c;
        
        for(int i =0;i<dimX;i++){
            RS0[i2] = B[i]; 
            i2++;
        }
    }
    
   public double [][] RetornaRS(){
        return RS;
    }
    
   public String[] RetornaRS0(){
        return RS0;
    }
    
   public int rDimF(){
        return NT;
    }

    

   
}
